package com.lznAdmin.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lznAdmin.base.common.util.RedisUtil;
import com.lznAdmin.system.entity.SysPermission;
import com.lznAdmin.system.entity.SysRole;
import com.lznAdmin.system.entity.SysUser;
import com.lznAdmin.system.mapper.SysUserMapper;
import com.lznAdmin.system.service.SysPermissionService;
import com.lznAdmin.system.service.SysRoleService;
import com.lznAdmin.system.service.SysUserRoleService;
import com.lznAdmin.system.service.SysUserService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * ServiceImpl<M extends BaseMapper<T>, T> 是对 IService接口中方法的实现
 * 第1个泛型 M 指定继承了 BaseMapper接口的子接口
 * 第2个泛型 T 指定实体类
 *
 * @Auther: 梦学谷 www.mengxuegu.com
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    RedisUtil redisUtil;
    @Autowired
    SysRoleService sysRoleService;

    @Autowired
    SysPermissionService sysPermissionService;

    @Autowired
    SysUserMapper sysUserMapper;

    @Autowired
    SysUserRoleService sysUserRoleService;

    @Override
    public SysUser findByUsername(String username) {
        if (StringUtils.isEmpty(username)) {
            return null;
        }
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public IPage<SysUser> selectUserPage(Page<SysUser> page, SysUser sysUser) {
        IPage<SysUser> sysUserIPage = baseMapper.selectUserPage(page, sysUser);
        List<SysUser> roleList = baseMapper.getRoleList();
        for (SysUser user : roleList) {
            Long id = user.getId();
            for (int j = 0; j < sysUserIPage.getRecords().size(); j++) {
                if (id.equals(sysUserIPage.getRecords().get(j).getId())) {
                    sysUserIPage.getRecords().get(j).setRoleIds(user.getRoleIds());
                    // logger.info("sysUserIPage111 = {}", sysUserIPage.getRecords().get(j).getRoleIds());
                }
            }
        }
        // logger.info("sysUserIPage = {}", sysUserIPage.getRecords());
        return sysUserIPage;
    }

    @Override
    public String getUserAuthorityInfo(Long userId) {
        // 根据传来Userid查询出user全部信息
        SysUser sysUser = baseMapper.selectById(userId);

        //  ROLE_admin,ROLE_normal,sys:user:list,....
        String authority = "";

        if (redisUtil.hasKey("GrantedAuthority:" + sysUser.getUsername())) {
            authority = (String) redisUtil.get("GrantedAuthority:" + sysUser.getUsername());

        } else {
            // 获取角色编码
            List<SysRole> roles = sysRoleService.list(new QueryWrapper<SysRole>()
                    .inSql("id", "select role_id from sys_user_role where user_id = " + userId));
            // logger.info("roles" + roles);

            if (roles.size() > 0) {
                String roleCodes = roles.stream().map(r -> "ROLE_" + r.getId()).collect(Collectors.joining(","));
                authority = roleCodes.concat(",");
            }

            // 获取菜单操作编码
            List<Long> menuIds = sysUserMapper.getNavMenuIds(userId);
            if (menuIds.size() > 0) {
                // logger.info("menuIds = {}", menuIds.toString());
                List<SysPermission> menus = sysPermissionService.listByIds(menuIds);
                String menuPerms = menus.stream().map(m -> m.getCode()).collect(Collectors.joining(","));

                authority = authority.concat(menuPerms);
            }

            redisUtil.set("GrantedAuthority:" + sysUser.getUsername(), authority, 60 * 60);
        }

        return authority;
    }

    @Override
    public void clearUserAuthorityInfo(String username) {
        redisUtil.del("GrantedAuthority:" + username);
    }

    @Override
    public void clearUserAuthorityInfoByRoleId(Long roleId) {

        List<SysUser> sysUsers = this.list(new QueryWrapper<SysUser>()
                .inSql("id", "select user_id from sys_user_role where role_id = " + roleId));

        sysUsers.forEach(u -> {
            this.clearUserAuthorityInfo(u.getUsername());
        });

    }

    @Override
    public void clearUserAuthorityInfoByMenuId(Long menuId) {
        List<SysUser> sysUsers = sysUserMapper.listByMenuId(menuId);

        sysUsers.forEach(u -> {
            this.clearUserAuthorityInfo(u.getUsername());
        });
    }


    @Override
    public List<SysPermission> getUserPermissions(Long userId) {
        return baseMapper.selectUserPermissions(userId);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean addUserAndRole(SysUser sysUser) throws RuntimeException {
        boolean b = this.save(sysUser);
        if (b) {
            Long userId = sysUser.getId();
            if (userId != null) {
                for (Long roleId : sysUser.getRoleIds()) {
                    Long ID = IdWorker.getId();
                    baseMapper.saveUserRole(ID, userId, roleId);
                }
            }
            return true;
        }
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean editUserAndRole(SysUser sysUser) throws Exception {
        boolean b = this.updateById(sysUser);
        if (b) {
            baseMapper.deleteUserRole(sysUser.getId());
            if (sysUser.getRoleIds().size() > 0) {
                for (Long roleId : sysUser.getRoleIds()) {
                    Long ID = IdWorker.getId();
                    baseMapper.saveUserRole(ID, sysUser.getId(), roleId);
                }
            }
            return true;
        }
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteUserAndRole(Long uid) {
        boolean b = this.removeById(uid);
        if (b) {
            // logger.info(String.valueOf(b));
            baseMapper.deleteUserRole(uid);
            return true;
        }
        return false;
    }
}
